/* vim: set expandtab shiftwidth=4: -*- mode: c++; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: nil -*-
qRPG
An RPG written to test Qt's Graphics View framework
Copyright (C) 2006 Wesley Crossman
Email: wesley@crossmans.net

You can redistribute and/or modify this software under the terms of the GNU
General Public License as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this
program; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
Suite 330, Boston, MA 02111-1307 USA */

#include "GameWindow.h"
#include "BoardCharacter.h"
#include "GameBoardScene.h"
#include "ClickableLabel.h"
#include <QtGui>

GameWindow::GameWindow() {
    setupUi(this);
    
    underFootLabelMapper = NULL;
    inventoryLabelMapper = NULL;
    inventoryPopupMapper = NULL;
    
    tbrUnderFoot = new QToolBar(tr("On Ground"), this);
    tbrUnderFoot->setMovable(false);
    QLabel *lblOnGround = new QLabel(tr("On Ground"), tbrUnderFoot);
    lblOnGround->setMinimumSize(90, 32); //XXX use tile height
    tbrUnderFoot->addWidget(lblOnGround);
    addToolBar(Qt::BottomToolBarArea, tbrUnderFoot);
    addToolBarBreak(Qt::BottomToolBarArea); //break
    //
    tbrInventory = new QToolBar(tr("Inventory"), this);
    tbrInventory->setMovable(false);
    QLabel *lblInventory = new QLabel(tr("Inventory"), tbrInventory);
    lblInventory->setMinimumSize(90, 32); //XXX use tile height
    tbrInventory->addWidget(lblInventory);
    addToolBar(Qt::BottomToolBarArea, tbrInventory);
    //
    tbrDebug = new QToolBar(tr("Debug"), this);
    chkDebugFullVision = new QCheckBox(tr("Full Vision"), tbrDebug);
	connect(chkDebugFullVision, SIGNAL(toggled(bool)), SLOT(debugFullVisionToggled(bool)));
	tbrDebug->addWidget(chkDebugFullVision);
    addToolBar(Qt::TopToolBarArea, tbrDebug);
    
    connect(aQuit, SIGNAL(activated()),
            SLOT(close()));
    connect(grvBoard->gameBoardScene(), SIGNAL(playerMoved()),
            SLOT(playerMoved()));
    connect(grvBoard->gameBoardScene(), SIGNAL(playerInventoryChanged()),
            SLOT(playerInventoryChanged()));
    connect(grvBoard->gameBoardScene(), SIGNAL(sigShowMessage(const QString &)),
            statusBar(), SLOT(showMessage(const QString &)));
}

void GameWindow::playerMoved() {
    delete underFootLabelMapper;
    underFootLabelMapper = new QSignalMapper(this);
    connect(underFootLabelMapper, SIGNAL(mapped(QWidget *)),
            SLOT(underFootLabelClicked(QWidget *)));
    foreach (QLabel *label, underFootLabels) delete label;
    underFootLabels.clear();

    GameBoardScene *scene = grvBoard->gameBoardScene();
    foreach (GameItem *item, scene->getUnderFoot()) {
        ClickableLabel *lblItem = new ClickableLabel(tbrUnderFoot);
        underFootLabelMapper->setMapping(lblItem, lblItem);
        connect(lblItem, SIGNAL(leftButtonPressed()), underFootLabelMapper, SLOT(map()));
        lblItem->setData(item);
        lblItem->setPixmap(item->item->pixmap());
        tbrUnderFoot->addWidget(lblItem);
        underFootLabels.append(lblItem);
    }
}

void GameWindow::playerInventoryChanged() {
    delete inventoryLabelMapper;
    inventoryLabelMapper = new QSignalMapper(this);
    connect(inventoryLabelMapper, SIGNAL(mapped(QWidget *)),
            SLOT(inventoryLabelClicked(QWidget *)));
    foreach (QLabel *label, inventoryLabels) delete label;
    inventoryLabels.clear();
    
    GameBoardScene *scene = grvBoard->gameBoardScene();
    foreach (GameItem *item, scene->getMe()->getChildren()) {
        ClickableLabel *lblItem = new ClickableLabel(tbrInventory);
        connect(item, SIGNAL(destroyed()), lblItem, SLOT(deleteLater()));
        inventoryLabelMapper->setMapping(lblItem, lblItem);
        connect(lblItem, SIGNAL(leftButtonPressed()), inventoryLabelMapper, SLOT(map()));
        lblItem->setData(item);
        lblItem->setPixmap(item->item->pixmap());
        tbrInventory->addWidget(lblItem);
        inventoryLabels.append(lblItem);
    }
}

void GameWindow::underFootLabelClicked(QWidget *widget) {
    ClickableLabel *label = dynamic_cast < ClickableLabel * >(widget);
    label->hide();
    GameItem *item = static_cast < GameItem * >(label->getData());
    item->getIntoItem(grvBoard->gameBoardScene()->getMe());
}

void GameWindow::inventoryLabelClicked(QWidget *widget) {
    delete inventoryPopupMapper;
    inventoryPopupMapper = new QSignalMapper(this);
    connect(inventoryPopupMapper, SIGNAL(mapped(const QString &)),
            SLOT(popupInventoryActionTriggered(const QString &)));
    const int popupOffset = 5;
    ClickableLabel *label = dynamic_cast < ClickableLabel * >(widget);
    inventoryPopupItem = static_cast < GameItem * >(label->getData());
    QMenu *popup = new QMenu(this);
    connect(popup, SIGNAL(triggered(QAction *)), popup, SLOT(deleteLater()));
    connect(popup, SIGNAL(triggered(QAction *)), SLOT(playerMoved()));
    popup->addAction(tr("Drop"), inventoryPopupItem, SLOT(getOut()))->setParent(popup);
    QStringList functions = inventoryPopupItem->getFunctions();
    foreach (QString function, functions) {
        QAction *action = popup->addAction(function);
        action->setParent(popup);
        connect(action, SIGNAL(triggered()), inventoryPopupMapper, SLOT(map()));
        inventoryPopupMapper->setMapping(action, function);
    }
    popup->popup(widget->mapToGlobal(
            QPoint(widget->width()-popupOffset,widget->height()-popupOffset)));
}

void GameWindow::popupInventoryActionTriggered(const QString &command) {
    GameBoardScene *scene = grvBoard->gameBoardScene();
    inventoryPopupItem->callFunction(scene->getMe(), command);
}

void GameWindow::debugFullVisionToggled(bool value) {
	GameBoardScene *scene = grvBoard->gameBoardScene();
	scene->changeLayerZValue(scene->getLayerIndex("shadow"), value ? -1000 : 1000);
}
